Fix Copilot seat organization attribution causing wrong DORA adoption denominator - #9049
Fix Copilot seat organization attribution causing wrong DORA adoption denominator#9049bramhanandlingala wants to merge 1 commit into
Conversation
|
Thank you for creating a PR so quickly and for helping me investigate this issue. Does this fix seats assigned through a central licensing organization? The change stores Would Product Org A and Product Org B still have zero denominators? Should licensed users be joined with organization membership, and could this scenario be added as a test? |
|
@anthonyhull-ford Thanks for looking into this closely — good catch. You're right that this doesn't cover centrally-licensed seats. I checked GitHub's docs, and when a seat is licensed through multiple orgs in the same enterprise, GitHub bills (and reports) only one org per seat, chosen by GitHub — so the seats API itself never exposes the user's other org memberships. That means Product Org A and B could still show zero denominators in that case, but it's not fixable from this endpoint alone; it'd need a separate join against org membership data. I'd like to keep that as a follow-up rather than block this fix, since it's a different data source and a bigger scope. Also — noticed the CI checks aren't triggering on this PR. Could someone approve the workflow run? |
Summary
Fixes #9041. Copilot seats from GitHub's enterprise API were being
tagged with the connection's "shell" org instead of the org that
actually granted the seat, which made the DORA dashboard's adoption
percentage wrong (often zero) for any org besides the shell org. Two
dashboard queries also mislabeled NULL adoption as the highest tier
instead of excluding it.
Root cause
seat_extractor.gohardcoded every seat's organization toconnection.Organization, ignoring the per-seatorganizationfield the enterprise seats endpoint actually returns.
CASEstatements usedELSEasa catch-all, so NULL adoption silently got labeled
>75%/highinstead of being excluded.
Fix
organizationfield(
metrics_extractor.go) and prefer it over the connection'sconfigured org, falling back only when the API doesn't supply one
(
seat_extractor.go).ELSEwith explicitWHEN+WHERE ... IS NOT NULLinboth dashboards' tier queries (MySQL and PostgreSQL).
tests covering org-scoped, enterprise-with-org, and
enterprise-with-empty-org cases.
Closes #9041